package com.datahandlers;

import com.gui.helper.CustomTableModel;
import com.gui.listeners.RemoveRecordTableModelListener;
import com.inventory.controllers.CategoryControllerRemote;
import com.inventory.entities.Category;
import com.util.ResourceLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author sithum
 */
public class CategoryDataHandler implements DataHandler {

    private List<Category> categoryList;
    private String[] tableHeaders = new String[]{ResourceLoader.getInstance().getProperty("category.column0"), ResourceLoader.getInstance().getProperty("category.column1"), new String()};
    private CustomTableModel model;
    private Object[][] tableData;
    private CategoryControllerRemote controller;
    private String[] categoryNames;
    private Map<String, String> editCategoryMap;
    private List<Category> data;
    private static int recordCount = 0;

    public CategoryDataHandler(Object cotroller) {
        try {
            this.init(cotroller);
        } catch (Exception ex) {
            Logger.getLogger(CategoryDataHandler.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void init(Object controller) throws Exception {
        this.controller = (CategoryControllerRemote) controller;
        categoryList = new ArrayList<Category>();
        editCategoryMap = new HashMap<String, String>();
        this.processData();
        model = new CustomTableModel(tableHeaders, tableData);
        CategoryDataHandler.recordCount = this.controller.count();
    }

    /**
     * Add a record from the user interface to be saved to a java.lang.List.
     * @param java.lang.Object - categoryName
     */
    public void addRecord(Object categoryName) {
        Category c = new Category();
        c.setCategoryId(++recordCount);
        c.setCategoryName(categoryName.toString());
        this.categoryList.add(c);
    }

    /**
     * Temporarily holds the old category name until the edit operation is completed.
     * @param categoryName
     */
    public void addEditRecord(Object key, Object categoryName) {
        Category c = controller.findCategoryByName(key.toString());
        if (c != null) {
            c.setCategoryName(categoryName.toString());
            this.categoryList.add(c);
        }
    }

    /**
     * Save all the records added by addRecord() method when users clicks save.
     * @throws java.lang.Exception
     */
    public void saveData() throws Exception {
        controller.create(categoryList);
        categoryList.clear();
        this.processData();
        model.setTableData(this.getTableData());
    }

    /**
     * Edit all the records edited by the user, when save is clicked.
     * @throws java.lang.Exception
     */
    public void editData() throws Exception {
        controller.edit(this.categoryList);
        this.categoryList.clear();
        this.processData();
        model.setTableData(this.getTableData());
    }

    /**
     * Process the data retrived from the database to display in a JTable.
     * @return java.lang.Object[][]
     * @throws java.lang.Exception
     */
    private void processData() throws Exception {
        setData(controller.findAll());
        this.processData(getData());
    }

    private void processData(List<Category> data) {
        Object[][] dataSet = new Object[data.size()][Category.class.getDeclaredFields().length];
        String[] names = new String[data.size()];
        int index = 0;
        for (Category category : data) {
            dataSet[index][0] = category.getCategoryId();
            dataSet[index][1] = category.getCategoryName();
            dataSet[index][2] = new Boolean(false);
            names[index] = category.getCategoryName();
            index++;
        }
        this.setCategoryNames(names);
        this.setTableData(dataSet);
    }

    public void remove(RemoveRecordTableModelListener listener) throws Exception {
        List<Object> garbageData = listener.getGarbageData();
        controller.delete(garbageData);
        this.processData();
        model.setTableData(this.getTableData());
        listener.getGarbageData().clear();
    }

    public void reflectEditChanges(Object value, int rowIndex, int columnIndex) {
        model.setValueAt(value, rowIndex, columnIndex);
    }

    /**
     * Returns true if the temporary storage for records is empty.
     * @return booleanS
     */
    public boolean temporaryStorageEmpty() {
        return categoryList.isEmpty();
    }

    public boolean tempEditStorageEmpty() {
        return editCategoryMap.isEmpty();
    }

    /**
     * @return the categoryNames
     */
    public String[] getCategoryNames() {
        return categoryNames;
    }

    /**
     * @param categoryNames the categoryNames to set
     */
    public void setCategoryNames(String[] categoryNames) {
        this.categoryNames = categoryNames;
    }

    /**
     * @return the editCategoryMap
     */
    public Map<String, String> getEditCategoryMap() {
        return editCategoryMap;
    }

    /**
     * @param editCategoryMap the editCategoryMap to set
     */
    public void setEditCategoryMap(Map<String, String> editCategoryList) {
        this.editCategoryMap = editCategoryList;
    }

    /**
     * @return the data
     */
    public List<Category> getData() {
        if (data == null) {
            data = new ArrayList<Category>();
        }
        return data;
    }

    /**
     * @param data the data to set
     */
    public void setData(List<Category> data) {
        this.data = data;
    }

    /**
     * @return the categoryList
     */
    public List<Category> getCategoryList() {
        return categoryList;
    }

    /**
     * @param categoryList the categoryList to set
     */
    public void setCategoryList(List<Category> categoryList) {
        this.categoryList = categoryList;
    }

    /**
     * @return the model
     */
    public CustomTableModel getModel() {
        return model;
    }

    /**
     * @param model the model to set
     */
    public void setModel(CustomTableModel model) {
        this.model = model;
    }

    /**
     * @return the tableData
     */
    public Object[][] getTableData() {
        return tableData;
    }

    /**
     * @param tableData the tableData to set
     */
    public void setTableData(Object[][] tableData) {
        this.tableData = tableData;
    }
}
